Neste relatório, iremos explorar os dados da atriz Julia Roberts. Os dados foram extraídos do RottenTomatoes.

Julia Fiona Roberts (Smyrna, 28 de outubro de 1967) é uma atriz e produtora norte-americana, vencedora do Oscar de Melhor Atriz por seu papel em Erin Brockovich, também atuou em Pretty Woman pelo qual se tornou conhecida em Hollywood.

## ANTES DE USAR
# Para criar data/movies.csv
import_data("julia_roberts") # ou com o ator/atriz que você escolher
NAs introduzidos por coerção
filmes = read_imported_data()

O objetivo aqui, é fazer um agrupamento dos filmes da atriz levando em consideração duas variáveis: bilheteria e avaliação.
Primeiro, vamos analisar separadamente cada uma dessas variáveis, utilizaremos também o ano de lançamento de cada filme para observar a variação durante o tempo.

Bilheteria

p = filmes %>% 
    ggplot(aes(size = 3, x = ano, 
               y = bilheteria, 
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m",
                            "\nAvaliação:", avaliacao,
                            "\nAno:",ano))) +
    geom_point(color = paleta[1]) +
    labs(title = "Variação da bilheteria ao longo dos anos", y = "Bilheteria", x = "Ano de lançamento")
ggplotly(p, tooltip = "text")

Há uma variação no faturamento dos filmes em que Julia Roberts atuou, o que mais se destacou nesse aspecto foi Ocean’s Eleven com bilheteria de 183.4 m. Não é possível perceber uma associação entre bilheteria e o ano, pois em alguns anos a bilheteria cai em comparação ao anterior, e logo após, no ano seguinte, o faturamente cresce.

p = filmes %>% 
    ggplot(aes(x = "", y = bilheteria, text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .4, size = 3, color = paleta[5]) + 
    labs(x = "", y="Bilheteria")
ggplotly(p, tooltip="text")

Observando esse gráfico é mais fácil verificar em quais grupos os filmes se encaixariam. Há diferentes abordagens que poderíamos tomar, acredito que separar os filmes nos seguintes grupos: bilheteria abaixo de 50, de 50 à 100, de 100 à 150 e acima de 150 (apenas o filme Ocean’s Eleven), seria uma boa abordagem.

Avaliação

p = filmes %>% 
    ggplot(aes(size = 3, x = ano, 
               y = avaliacao, 
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m",
                            "\nAvaliação:", avaliacao,
                            "\nAno:",ano))) +
    geom_point(color = paleta[1]) +
    labs(title = "Variação da avaliação ao longo dos anos", y = "Avaliação", x = "Ano de lançamento")
ggplotly(p, tooltip = "text")

Entre 2003 e 2006 a avaliação dos filmes crescreu consideravelmente, porém, a partir de 2009, os filmes não tiveram boa avaliação, em comparação aos anos anteriores, mas, logo em 2011, os filmes lançados voltaram a serem bem avaliados. Não existe nenhum padrão, a variação da avaliação é muito alta ao longo dos anos.

p = filmes %>% 
    ggplot(aes(x = "", y = avaliacao, text = paste("Filme:",filme,
                            "\nAvaliação:",
                            avaliacao,"m"))) + 
    geom_jitter(width = .05, alpha = .4, size = 3, color = paleta[5]) + 
    labs(x = "", y="Bilheteria")
ggplotly(p, tooltip="text")

De acordo com o gráfico acima, ainda assim, não fica muito clara a definição dos grupos, mas poderíamos separar em: filmes com avaliação abaixo de 40 e acima de 40.

Agrupamento

Agora utilizando as duas variáveis disponíveis, avaliação e bilheteria, vamos observar como os filmes se dividem melhor, em quantos grupos.

Normalização das variávies

Para tentar agrupar os filmes em grupos, é importante perceber que as escalas de bilheteria e avaliação são bem diferentes. Então, abaixo é feito a normalização das variáveis.

m_transformado = filmes %>% 
    mutate(bilheteria_log = as.vector(scale(log10(bilheteria))), 
           avaliacao_scaled = as.vector(scale(avaliacao)))
summary(m_transformado %>% select(bilheteria_log, avaliacao_scaled))
 bilheteria_log     avaliacao_scaled  
 Min.   :-1.38709   Min.   :-2.03083  
 1st Qu.:-0.98944   1st Qu.:-0.74741  
 Median : 0.07942   Median : 0.06543  
 Mean   : 0.00000   Mean   : 0.00000  
 3rd Qu.: 0.65103   3rd Qu.: 0.62158  
 Max.   : 1.80801   Max.   : 1.30607  

Escolhendo o K

É utilizado o “Gap Static Calculation” para escolher o melhor valor para o k.

plot_clusgap = function(clusgap, title = "Gap Statistic calculation results") {
    require("ggplot2")
    gstab = data.frame(clusgap$Tab, k = 1:nrow(clusgap$Tab))
    p = ggplot(gstab, aes(k, gap)) + geom_line() + geom_point(size = 5)
    p = p + geom_errorbar(aes(ymax = gap + SE.sim, ymin = gap - SE.sim), width = .2)
    p = p + ggtitle(title)
    return(p)
}
gaps <- m_transformado %>% 
    select(bilheteria_log, avaliacao) %>% 
    clusGap(FUN = kmeans, nstart = 20, K.max = 8, B = 200)
Clustering k = 1,2,..., K.max (= 8): .. done
Bootstrapping, b = 1,2,..., B (= 200)  [one "." per sample]:
.................................................. 50 
.................................................. 100 
.................................................. 150 
.................................................. 200 
plot_clusgap(gaps)

Agrupamento K-means

Com a execução do Gap Statics é possível perceber que o melhor valor para o K é 5. Logo, assumindo assim esse valor, executamos o algoritmo do k-means.

set.seed(12345)
n_clusters = 5
# O agrupamento de fato:
cluster = m_transformado %>% 
    select(bilheteria_log, avaliacao_scaled) %>% 
    kmeans(centers = n_clusters, nstart = 20)
agrupado = cluster %>% 
    augment(m_transformado)
#p = agrupado %>% 
#    ggplot(aes(x = avaliacao_scaled, y = bilheteria_log, color = .cluster))  + 
#    geom_point(size = 3)
p1 = agrupado %>% 
    ggplot(aes(x = avaliacao, y = bilheteria, color = .cluster, label=filme))  + 
    geom_point(size = 3)+
    scale_y_log10()
ggscatter(agrupado, x="avaliacao", y="bilheteria", color=".cluster")+
    stat_chull(aes(fill = .cluster), alpha=0.3, geom="polygon")+
    xlab("Avaliação")+
    ylab("Bilheteria")

ggplotly(p1)

Podemos perceber a presença de 5 grupos de filmes da atriz Julia Roberts, vamos chama-lós de:

  • Bem avaliados e bem faturados: Grupo em cor vermelho, número 1. Aqui neste grupo temos os filmes com as melhores avaliações e também as maiores bilheterias. São filmes de muito sucesso que são caracterizados pelo drama e ação.

  • Comédia Romântica Fracassadas: Grupo em cor mostarda, número 2. Os filmes neste grupo são todos do gênero comédia romântica. Eles não são bem sucedidos, pois um deles possui a pior avaliação em comparação com os demais, além disso a bilheteria foi muito baixa.

  • Romance: Grupo em verde, número 3. Os filmes neste grupo são caracterizados pelo romance. Possuem bilheteria entre 50 e 120. Não foram muito bem avaliados.

  • Comédia e Drama: Grupo em azul, número 4. Os filmes deste grupo tiveram avaliação bem parecidas entre 60 e 70, e bilheteria muito baixa, menor que 50. Não foram bem vendidos, mas são ótimos filmes.

  • Avaliados na média: Grupo em rosa, número 5. Aqui neste grupo os filmes tiveram avaliação na média, acredito que agradaram a metade do público e a outra metade não.

LS0tCnRpdGxlOiAiVGlwb3MgZGUgZmlsbWUgZGUgSnVsaWEgUm9iZXJ0cyIKYXV0aG9yOiAiQWxpY2UgRmVybmFuZGVzIFNpbHZhIgpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICAgIGRmX3ByaW50OiBwYWdlZAogICAgICAgIHRvYzogeWVzCiAgICAgICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGh0bWxfbm90ZWJvb2s6CiAgICAgICAgdG9jOiB5ZXMKICAgICAgICB0b2NfZmxvYXQ6IHllcwp0aGVtZTogc2FuZHN0b25lCi0tLQoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShnZ2RlbmRybykKbGlicmFyeShicm9vbSkKbGlicmFyeShnZ3B1YnIpCgpzb3VyY2UoaGVyZTo6aGVyZSgiY29kZS9saWIuUiIpKQp0aGVtZV9zZXQodGhlbWVfcmVwb3J0KCkpCgprbml0cjo6b3B0c19jaHVuayRzZXQodGlkeSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gNiwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQgPSA1LAogICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUpCgpwYWxldGEgPSBjKCIjNDA0RTREIiwKICAgICAgICAgICAiIzkyRENFNSIsCiAgICAgICAgICAgIiM5MzhCQTEiLAogICAgICAgICAgICIjMkQzMTQyIiwKICAgICAgICAgICAiI0Y0NzQzQiIpCmBgYAoKTmVzdGUgcmVsYXTDs3JpbywgaXJlbW9zIGV4cGxvcmFyIG9zIGRhZG9zIGRhIGF0cml6IEp1bGlhIFJvYmVydHMuIE9zIGRhZG9zIGZvcmFtIGV4dHJhw61kb3MgZG8gW1JvdHRlblRvbWF0b2VzXShodHRwczovL3d3dy5yb3R0ZW50b21hdG9lcy5jb20vKS4KCkp1bGlhIEZpb25hIFJvYmVydHMgKFNteXJuYSwgMjggZGUgb3V0dWJybyBkZSAxOTY3KSDDqSB1bWEgYXRyaXogZSBwcm9kdXRvcmEgbm9ydGUtYW1lcmljYW5hLCB2ZW5jZWRvcmEgZG8gT3NjYXIgZGUgTWVsaG9yIEF0cml6IHBvciBzZXUgcGFwZWwgZW0gRXJpbiBCcm9ja292aWNoLCB0YW1iw6ltIGF0dW91IGVtIFByZXR0eSBXb21hbiBwZWxvIHF1YWwgc2UgdG9ybm91IGNvbmhlY2lkYSBlbSBIb2xseXdvb2QuCgpgYGB7cn0KIyMgQU5URVMgREUgVVNBUgojIFBhcmEgY3JpYXIgZGF0YS9tb3ZpZXMuY3N2CmltcG9ydF9kYXRhKCJqdWxpYV9yb2JlcnRzIikgIyBvdSBjb20gbyBhdG9yL2F0cml6IHF1ZSB2b2PDqiBlc2NvbGhlcgpgYGAKCgpgYGB7ciByZWFkfQpmaWxtZXMgPSByZWFkX2ltcG9ydGVkX2RhdGEoKQpgYGAKCgpPIG9iamV0aXZvIGFxdWksIMOpIGZhemVyIHVtIGFncnVwYW1lbnRvIGRvcyBmaWxtZXMgZGEgYXRyaXogbGV2YW5kbyBlbSBjb25zaWRlcmHDp8OjbyBkdWFzIHZhcmnDoXZlaXM6IGJpbGhldGVyaWEgZSBhdmFsaWHDp8Ojby4KPC9icj4KUHJpbWVpcm8sIHZhbW9zIGFuYWxpc2FyIHNlcGFyYWRhbWVudGUgY2FkYSB1bWEgZGVzc2FzIHZhcmnDoXZlaXMsIHV0aWxpemFyZW1vcyB0YW1iw6ltIG8gYW5vIGRlIGxhbsOnYW1lbnRvIGRlIGNhZGEgZmlsbWUgcGFyYSBvYnNlcnZhciBhIHZhcmlhw6fDo28gZHVyYW50ZSBvIHRlbXBvLgoKIyNCaWxoZXRlcmlhCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KcCA9IGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHNpemUgPSAzLCB4ID0gYW5vLCAKICAgICAgICAgICAgICAgeSA9IGJpbGhldGVyaWEsIAogICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5CaWxoZXRlcmlhOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWxoZXRlcmlhLCJtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkF2YWxpYcOnw6NvOiIsIGF2YWxpYWNhbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkFubzoiLGFubykpKSArCiAgICBnZW9tX3BvaW50KGNvbG9yID0gcGFsZXRhWzFdKSArCiAgICBsYWJzKHRpdGxlID0gIlZhcmlhw6fDo28gZGEgYmlsaGV0ZXJpYSBhbyBsb25nbyBkb3MgYW5vcyIsIHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQW5vIGRlIGxhbsOnYW1lbnRvIikKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikKYGBgCgpIw6EgdW1hIHZhcmlhw6fDo28gbm8gZmF0dXJhbWVudG8gZG9zIGZpbG1lcyBlbSBxdWUgSnVsaWEgUm9iZXJ0cyBhdHVvdSwgbyBxdWUgbWFpcyBzZSBkZXN0YWNvdSBuZXNzZSBhc3BlY3RvIGZvaSAqT2NlYW4ncyBFbGV2ZW4qIGNvbSBiaWxoZXRlcmlhIGRlIDE4My40IG0uIE7Do28gw6kgcG9zc8OtdmVsIHBlcmNlYmVyIHVtYSBhc3NvY2lhw6fDo28gZW50cmUgYmlsaGV0ZXJpYSBlIG8gYW5vLCBwb2lzIGVtIGFsZ3VucyBhbm9zIGEgYmlsaGV0ZXJpYSBjYWkgZW0gY29tcGFyYcOnw6NvIGFvIGFudGVyaW9yLCBlIGxvZ28gYXDDs3MsIG5vIGFubyBzZWd1aW50ZSwgbyBmYXR1cmFtZW50ZSBjcmVzY2UuCgpgYGB7cn0KcCA9IGZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiIiwgeSA9IGJpbGhldGVyaWEsIHRleHQgPSBwYXN0ZSgiRmlsbWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkJpbGhldGVyaWE6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpbGhldGVyaWEsIm0iKSkpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wNSwgYWxwaGEgPSAuNCwgc2l6ZSA9IDMsIGNvbG9yID0gcGFsZXRhWzVdKSArIAogICAgbGFicyh4ID0gIiIsIHk9IkJpbGhldGVyaWEiKQpnZ3Bsb3RseShwLCB0b29sdGlwPSJ0ZXh0IikKYGBgCgpPYnNlcnZhbmRvIGVzc2UgZ3LDoWZpY28gw6kgbWFpcyBmw6FjaWwgdmVyaWZpY2FyIGVtIHF1YWlzIGdydXBvcyBvcyBmaWxtZXMgc2UgZW5jYWl4YXJpYW0uIEjDoSBkaWZlcmVudGVzIGFib3JkYWdlbnMgcXVlIHBvZGVyw61hbW9zIHRvbWFyLCBhY3JlZGl0byBxdWUgc2VwYXJhciBvcyBmaWxtZXMgbm9zIHNlZ3VpbnRlcyBncnVwb3M6IGJpbGhldGVyaWEgYWJhaXhvIGRlIDUwLCBkZSA1MCDDoCAxMDAsIGRlIDEwMCDDoCAxNTAgZSBhY2ltYSBkZSAxNTAgKGFwZW5hcyBvIGZpbG1lICpPY2VhbidzIEVsZXZlbiopLCBzZXJpYSB1bWEgYm9hIGFib3JkYWdlbS4gCgojI0F2YWxpYcOnw6NvCmBgYHtyfQpwID0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoc2l6ZSA9IDMsIHggPSBhbm8sIAogICAgICAgICAgICAgICB5ID0gYXZhbGlhY2FvLCAKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlsaGV0ZXJpYSwibSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5Bbm86Iixhbm8pKSkgKwogICAgZ2VvbV9wb2ludChjb2xvciA9IHBhbGV0YVsxXSkgKwogICAgbGFicyh0aXRsZSA9ICJWYXJpYcOnw6NvIGRhIGF2YWxpYcOnw6NvIGFvIGxvbmdvIGRvcyBhbm9zIiwgeSA9ICJBdmFsaWHDp8OjbyIsIHggPSAiQW5vIGRlIGxhbsOnYW1lbnRvIikKZ2dwbG90bHkocCwgdG9vbHRpcCA9ICJ0ZXh0IikKYGBgCgpFbnRyZSAyMDAzIGUgMjAwNiBhIGF2YWxpYcOnw6NvIGRvcyBmaWxtZXMgY3Jlc2NyZXUgY29uc2lkZXJhdmVsbWVudGUsIHBvcsOpbSwgYSBwYXJ0aXIgZGUgMjAwOSwgb3MgZmlsbWVzIG7Do28gdGl2ZXJhbSBib2EgYXZhbGlhw6fDo28sIGVtIGNvbXBhcmHDp8OjbyBhb3MgYW5vcyBhbnRlcmlvcmVzLCBtYXMsIGxvZ28gZW0gMjAxMSwgb3MgZmlsbWVzIGxhbsOnYWRvcyB2b2x0YXJhbSBhIHNlcmVtIGJlbSBhdmFsaWFkb3MuIE7Do28gZXhpc3RlIG5lbmh1bSBwYWRyw6NvLCBhIHZhcmlhw6fDo28gZGEgYXZhbGlhw6fDo28gw6kgbXVpdG8gYWx0YSBhbyBsb25nbyBkb3MgYW5vcy4KCmBgYHtyfQpwID0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9ICIiLCB5ID0gYXZhbGlhY2FvLCB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhbGlhY2FvLCJtIikpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDUsIGFscGhhID0gLjQsIHNpemUgPSAzLCBjb2xvciA9IHBhbGV0YVs1XSkgKyAKICAgIGxhYnMoeCA9ICIiLCB5PSJCaWxoZXRlcmlhIikKZ2dwbG90bHkocCwgdG9vbHRpcD0idGV4dCIpCmBgYAoKRGUgYWNvcmRvIGNvbSBvIGdyw6FmaWNvIGFjaW1hLCBhaW5kYSBhc3NpbSwgbsOjbyBmaWNhIG11aXRvIGNsYXJhIGEgZGVmaW5pw6fDo28gZG9zIGdydXBvcywgbWFzIHBvZGVyw61hbW9zIHNlcGFyYXIgZW06IGZpbG1lcyBjb20gYXZhbGlhw6fDo28gYWJhaXhvIGRlIDQwIGUgYWNpbWEgZGUgNDAuCgojI0FncnVwYW1lbnRvCgpBZ29yYSB1dGlsaXphbmRvIGFzIGR1YXMgdmFyacOhdmVpcyBkaXNwb27DrXZlaXMsIGBhdmFsaWHDp8Ojb2AgZSBgYmlsaGV0ZXJpYWAsIHZhbW9zIG9ic2VydmFyIGNvbW8gb3MgZmlsbWVzIHNlIGRpdmlkZW0gbWVsaG9yLCBlbSBxdWFudG9zIGdydXBvcy4gCgojIyNOb3JtYWxpemHDp8OjbyBkYXMgdmFyacOhdmllcwoKUGFyYSB0ZW50YXIgYWdydXBhciBvcyBmaWxtZXMgZW0gZ3J1cG9zLCDDqSBpbXBvcnRhbnRlIHBlcmNlYmVyIHF1ZSBhcyBlc2NhbGFzIGRlIGJpbGhldGVyaWEgZSBhdmFsaWHDp8OjbyBzw6NvIGJlbSBkaWZlcmVudGVzLgpFbnTDo28sIGFiYWl4byDDqSBmZWl0byBhIG5vcm1hbGl6YcOnw6NvIGRhcyB2YXJpw6F2ZWlzLgoKYGBge3J9Cm1fdHJhbnNmb3JtYWRvID0gZmlsbWVzICU+JSAKICAgIG11dGF0ZShiaWxoZXRlcmlhX2xvZyA9IGFzLnZlY3RvcihzY2FsZShsb2cxMChiaWxoZXRlcmlhKSkpLCAKICAgICAgICAgICBhdmFsaWFjYW9fc2NhbGVkID0gYXMudmVjdG9yKHNjYWxlKGF2YWxpYWNhbykpKQoKc3VtbWFyeShtX3RyYW5zZm9ybWFkbyAlPiUgc2VsZWN0KGJpbGhldGVyaWFfbG9nLCBhdmFsaWFjYW9fc2NhbGVkKSkKYGBgCgojIyNFc2NvbGhlbmRvIG8gSwoKw4kgdXRpbGl6YWRvIG8g4oCcR2FwIFN0YXRpYyBDYWxjdWxhdGlvbuKAnSBwYXJhIGVzY29saGVyIG8gbWVsaG9yIHZhbG9yIHBhcmEgbyBrLgoKYGBge3J9CnBsb3RfY2x1c2dhcCA9IGZ1bmN0aW9uKGNsdXNnYXAsIHRpdGxlID0gIkdhcCBTdGF0aXN0aWMgY2FsY3VsYXRpb24gcmVzdWx0cyIpIHsKICAgIHJlcXVpcmUoImdncGxvdDIiKQogICAgZ3N0YWIgPSBkYXRhLmZyYW1lKGNsdXNnYXAkVGFiLCBrID0gMTpucm93KGNsdXNnYXAkVGFiKSkKICAgIHAgPSBnZ3Bsb3QoZ3N0YWIsIGFlcyhrLCBnYXApKSArIGdlb21fbGluZSgpICsgZ2VvbV9wb2ludChzaXplID0gNSkKICAgIHAgPSBwICsgZ2VvbV9lcnJvcmJhcihhZXMoeW1heCA9IGdhcCArIFNFLnNpbSwgeW1pbiA9IGdhcCAtIFNFLnNpbSksIHdpZHRoID0gLjIpCiAgICBwID0gcCArIGdndGl0bGUodGl0bGUpCiAgICByZXR1cm4ocCkKfQpgYGAKCmBgYHtyfQpnYXBzIDwtIG1fdHJhbnNmb3JtYWRvICU+JSAKICAgIHNlbGVjdChiaWxoZXRlcmlhX2xvZywgYXZhbGlhY2FvKSAlPiUgCiAgICBjbHVzR2FwKEZVTiA9IGttZWFucywgbnN0YXJ0ID0gMjAsIEsubWF4ID0gOCwgQiA9IDIwMCkKcGxvdF9jbHVzZ2FwKGdhcHMpCmBgYAoKIyMjQWdydXBhbWVudG8gSy1tZWFucwoKQ29tIGEgZXhlY3XDp8OjbyBkbyBHYXAgU3RhdGljcyDDqSBwb3Nzw612ZWwgcGVyY2ViZXIgcXVlIG8gbWVsaG9yIHZhbG9yIHBhcmEgbyBLIMOpIDUuIExvZ28sIGFzc3VtaW5kbyBhc3NpbSBlc3NlIHZhbG9yLCBleGVjdXRhbW9zIG8gYWxnb3JpdG1vIGRvIGstbWVhbnMuCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNDUpCm5fY2x1c3RlcnMgPSA1CmNsdXN0ZXIgPSBtX3RyYW5zZm9ybWFkbyAlPiUgCiAgICBzZWxlY3QoYmlsaGV0ZXJpYV9sb2csIGF2YWxpYWNhb19zY2FsZWQpICU+JSAKICAgIGttZWFucyhjZW50ZXJzID0gbl9jbHVzdGVycywgbnN0YXJ0ID0gMjApCmFncnVwYWRvID0gY2x1c3RlciAlPiUgCiAgICBhdWdtZW50KG1fdHJhbnNmb3JtYWRvKQpwMSA9IGFncnVwYWRvICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF2YWxpYWNhbywgeSA9IGJpbGhldGVyaWEsIGNvbG9yID0gLmNsdXN0ZXIsIGxhYmVsPWZpbG1lKSkgICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAzKSsKICAgIHNjYWxlX3lfbG9nMTAoKQpnZ3NjYXR0ZXIoYWdydXBhZG8sIHg9ImF2YWxpYWNhbyIsIHk9ImJpbGhldGVyaWEiLCBjb2xvcj0iLmNsdXN0ZXIiKSsKICAgIHN0YXRfY2h1bGwoYWVzKGZpbGwgPSAuY2x1c3RlciksIGFscGhhPTAuMywgZ2VvbT0icG9seWdvbiIpKwogICAgeGxhYigiQXZhbGlhw6fDo28iKSsKICAgIHlsYWIoIkJpbGhldGVyaWEiKQpnZ3Bsb3RseShwMSkKYGBgCgoKClBvZGVtb3MgcGVyY2ViZXIgYSBwcmVzZW7Dp2EgZGUgNSBncnVwb3MgZGUgZmlsbWVzIGRhIGF0cml6IEp1bGlhIFJvYmVydHMsIHZhbW9zIGNoYW1hLWzDs3MgZGU6CgoqIEJlbSBhdmFsaWFkb3MgZSBiZW0gZmF0dXJhZG9zOiBHcnVwbyBlbSBjb3IgdmVybWVsaG8sIG7Dum1lcm8gMS4gQXF1aSBuZXN0ZSBncnVwbyB0ZW1vcyBvcyBmaWxtZXMgY29tIGFzIG1lbGhvcmVzIGF2YWxpYcOnw7VlcyBlIHRhbWLDqW0gYXMgbWFpb3JlcyBiaWxoZXRlcmlhcy4gU8OjbyBmaWxtZXMgZGUgbXVpdG8gc3VjZXNzbyBxdWUgc8OjbyBjYXJhY3Rlcml6YWRvcyBwZWxvIGRyYW1hIGUgYcOnw6NvLgoKKiBDb23DqWRpYSBSb23Dom50aWNhIEZyYWNhc3NhZGFzOiBHcnVwbyBlbSBjb3IgbW9zdGFyZGEsIG7Dum1lcm8gMi4gT3MgZmlsbWVzIG5lc3RlIGdydXBvIHPDo28gdG9kb3MgZG8gZ8OqbmVybyBjb23DqWRpYSByb23Dom50aWNhLiBFbGVzIG7Do28gc8OjbyBiZW0gc3VjZWRpZG9zLCBwb2lzIHVtIGRlbGVzIHBvc3N1aSBhIHBpb3IgYXZhbGlhw6fDo28gZW0gY29tcGFyYcOnw6NvIGNvbSBvcyBkZW1haXMsIGFsw6ltIGRpc3NvIGEgYmlsaGV0ZXJpYSBmb2kgbXVpdG8gYmFpeGEuCgoqIFJvbWFuY2U6IEdydXBvIGVtIHZlcmRlLCBuw7ptZXJvIDMuIE9zIGZpbG1lcyBuZXN0ZSBncnVwbyBzw6NvIGNhcmFjdGVyaXphZG9zIHBlbG8gcm9tYW5jZS4gUG9zc3VlbSBiaWxoZXRlcmlhIGVudHJlIDUwIGUgMTIwLiBOw6NvIGZvcmFtIG11aXRvIGJlbSBhdmFsaWFkb3MuCgoqIENvbcOpZGlhIGUgRHJhbWE6IEdydXBvIGVtIGF6dWwsIG7Dum1lcm8gNC4gT3MgZmlsbWVzIGRlc3RlIGdydXBvIHRpdmVyYW0gYXZhbGlhw6fDo28gYmVtIHBhcmVjaWRhcyBlbnRyZSA2MCBlIDcwLCBlIGJpbGhldGVyaWEgbXVpdG8gYmFpeGEsIG1lbm9yIHF1ZSA1MC4gTsOjbyBmb3JhbSBiZW0gdmVuZGlkb3MsIG1hcyBzw6NvIMOzdGltb3MgZmlsbWVzLgoKKiBBdmFsaWFkb3MgbmEgbcOpZGlhOiBHcnVwbyBlbSByb3NhLCBuw7ptZXJvIDUuIEFxdWkgbmVzdGUgZ3J1cG8gb3MgZmlsbWVzIHRpdmVyYW0gYXZhbGlhw6fDo28gbmEgbcOpZGlhLCBhY3JlZGl0byBxdWUgYWdyYWRhcmFtIGEgbWV0YWRlIGRvIHDDumJsaWNvIGUgYSBvdXRyYSBtZXRhZGUgbsOjby4K